package graphSample.SerialMachine;

import java.util.HashMap;

import core.Entity;
import core.Graph;
import core.Process;

/**
 * ODF 不可中断
 * @author karajan
 *
 */
public class SerialMachineOR extends SerialMachine{
	public SerialMachineOR(int id, int[] bc, double[] mtbf, double mttr) {
		
		this.id = id;
		bufferCapacity = bc;
		MTBF = mtbf; 
		MTTR = mttr;

		g = new Graph("SerialMachineOR"+id);
		
		// Entities
		Entity p_store = new Entity(g, "p_store");
		p_store.addVariable("$pId","INT");
		p_store.addVariable("$pBId","INT");
		p_store.addVariable("$pATime","DOUBLE");
		
		Entity p_working = new Entity(g, "p_working");
		p_working.addVariable("$pId","INT");
		p_working.addVariable("$pMId","INT");
		
		Entity p_wait = new Entity(g, "p_wait");
		p_wait.addVariable("$pId","INT");
		p_wait.addVariable("$pMId","INT");
		p_wait.addVariable("$pRTime","DOUBLE");
		
		Entity m_working = new Entity(g, "m_working");
		m_working.addVariable("$mId","INT");
		m_working.addVariable("$mWTime","DOUBLE");
		m_working.addVariable("$mFTime","DOUBLE");
		m_working.addVariable("$expectedF", "DOUBLE");
		
		Entity m_idle = new Entity(g, "m_idle");
		m_idle.addVariable("$mId", "INT");
		m_idle.addVariable("$mATime","DOUBLE");
		m_idle.addVariable("$expectedF", "DOUBLE");
		
		Entity m_faild = new Entity(g, "m_faild");
		m_faild.addVariable("$mId", "INT");
		m_faild.addVariable("$mRTime","DOUBLE");
		m_faild.addVariable("$expectedF", "DOUBLE");
		
		Entity buffer = new Entity(g, "buffer");
		buffer.addVariable("$bId", "INT");
		buffer.addVariable("$stock", "INT");
		buffer.addVariable("$capacity", "INT");
		buffer.addVariable("$bUTime","DOUBLE");
		
		// Processes
		Process Start = new Process(g, "Start", "$pBId = $bId AND $pBId = $mId");
		Start.addEntityIn(p_store); Start.addEntityIn(m_idle); Start.addEntityIn(buffer);
		Start.addEntityOut(p_working); Start.addEntityOut(m_working); Start.addEntityOut(buffer);
		Start.addEvalItem("$pMId=$mId");
		Start.addEvalItem("$mWTime=Max[{$pATime,$mATime}]+1");
		Start.addEvalItem("$mFTime=Max[{$pATime,$mATime}]-Log[RandomReal[]]*$expectedF");
		Start.addEvalItem("$stock=$stock-1");
		Start.addEvalItem("$bUTime=Max[{$pATime,$mATime}]");
		
		Process Finish = new Process(g, "Finish", "$mWTime <= $mFTime AND $pMId = $mId AND $bId = $pMId +1 And $stock < $capacity");
		Finish.addEntityIn(p_working); Finish.addEntityIn(m_working); Finish.addEntityIn(buffer);
		Finish.addEntityOut(p_store); Finish.addEntityOut(m_idle); Finish.addEntityOut(buffer);
		Finish.addEvalItem("$pBId=$bId");
		Finish.addEvalItem("$pATime=Max[{$mWTime,$bUTime}]");
		Finish.addEvalItem("$mATime=$pATime");
		Finish.addEvalItem("$stock=$stock+1");
		Finish.addEvalItem("$bUTime=$pATime");
		
		Process Failure = new Process(g, "Failure", "$mWTime > $mFTime AND $pMId = $mId");
		Failure.addEntityIn(p_working); Failure.addEntityIn(m_working);
		Failure.addEntityOut(p_wait); Failure.addEntityOut(m_faild);
		Failure.addEvalItem("$mRTime=$mFTime-Log[RandomReal[]]*"+String.valueOf(MTTR));
		Failure.addEvalItem("$pRTime=$mWTime-$mFTime");
		
		Process Restart = new Process(g, "Restart", "$pMId = $mId");
		Restart.addEntityIn(p_wait); Restart.addEntityIn(m_faild);
		Restart.addEntityOut(p_working); Restart.addEntityOut(m_working);
		Restart.addEvalItem("$mWTime=$mRTime+$pRTime");
		Restart.addEvalItem("$mFTime=$mRTime-Log[RandomReal[]]*$expectedF");
		
		//Add 10000 pieces in p_store
		HashMap<String,String> token;
		for(int i=0;i<10000;i++){
			token = new HashMap<String,String>();
			token.put("$pId", String.valueOf(i));
			token.put("$pBId", "0");
			token.put("$pATime", "0");
			p_store.addToken(token);
		}
		
		// Add 6 buffers in buffer
		for (int i = 0; i < 6; i++) {
			token = new HashMap<String, String>();
			token.put("$bId", String.valueOf(i));
			if (i == 0) {
				token.put("$stock", "10000");
				token.put("$capacity", "1000000");
			} else if (i == 5) {
				token.put("$stock", "0");
				token.put("$capacity", "1000000");
			} else if(i == 1) {
				token.put("$stock", "0");
				token.put("$capacity", String.valueOf(bufferCapacity[0]));
			} else if(i == 2) {
				token.put("$stock", "0");
				token.put("$capacity", String.valueOf(bufferCapacity[1]));
			} else if(i == 3) {
				token.put("$stock", "0");
				token.put("$capacity", String.valueOf(bufferCapacity[2]));
			} else if(i == 4) {
				token.put("$stock", "0");
				token.put("$capacity", String.valueOf(bufferCapacity[3]));
			}

			token.put("$bUTime", "0");
			buffer.addToken(token);
		}

		// Add 5 machines in m_idle
		for (int i = 0; i < 5; i++) {
			token = new HashMap<String, String>();
			token.put("$mId", String.valueOf(i));
			token.put("$mATime", "0");
			if(i==0){
				token.put("$expectedF", String.valueOf(mtbf[0]));
			} else if (i==1){
				token.put("$expectedF", String.valueOf(mtbf[1]));
			} else if (i==2){
				token.put("$expectedF", String.valueOf(mtbf[2]));
			} else if (i==3){
				token.put("$expectedF", String.valueOf(mtbf[3]));
			} else if (i==4){
				token.put("$expectedF", String.valueOf(mtbf[4]));
			}
			m_idle.addToken(token);
		}
	}
}
